package cn.doitedu.day04.adv;

import java.util.ArrayList;
import java.util.List;

//定义一个新的高级的List，具备Java中List的全部功能，并且在扩展一些新的方法，例如map、filter、flatMap、reduce
//这个新的高级的List，可以支持多种数据类型
public class MyAdvList<A> extends ArrayList<A> {

    //泛型方法，在方法的返回值前面先定义泛型，在使用
    public <B> MyAdvList<B> map(MyFunction1<A, B> func) {

        //1.定义一个新的List
        MyAdvList<B> nList = new MyAdvList<>();
        //2.遍历原来List中的数据
        for (A a : this) {
            //应用外部传入的逻辑
            B r = func.apply(a);
            //添加新的数据到新的List
            nList.add(r);
        }
        //返回新的List
        return nList;
    }

    public MyAdvList<A> filter(MyFunction1<A, Boolean> func) {

        //1.定义一个新的List
        MyAdvList<A> nList = new MyAdvList<>();
        //2.遍历原来List中的数据
        for (A a : this) {
            //3.应用外部的过滤逻辑
            Boolean flag = func.apply(a);
            if(flag) {
                nList.add(a);
            }
        }
        //返回新的List
        return nList;

    }

    /**
     * 实现FlatMap方法
     */
    public <B> MyAdvList<B> flatMap(MyFunction1<A, Iterable<B>> func) {

        //1.定义一个新的List
        MyAdvList<B> nList = new MyAdvList<>();
        //遍历老的List
        for (A a : this) {
            //应用外部传入的函数
            Iterable<B> it = func.apply(a);
            //再循环it
            for (B b : it) {
                //变化后的数据，添加到新的List
                nList.add(b);
            }
        }
        //返回新的List
        return nList;

    }


    public A reduce(MyFunction2<A, A, A> func) {
        //定义一个临时变量
        A acc = null;
        //定义一个布尔类型的变量
        boolean isFirst = true;
        //遍历原来List中的数据
        for (A a : this) {
            if (isFirst) {
                acc = a; //不聚合，先将数据攒起来
                isFirst = false;
            } else {
                //初始值或中间累计的结果，与新遍历出的数据进行聚合
                //将聚合的结果，再赋值给acc
                acc = func.apply(acc, a);
            }
        }
        return acc;
    }



}
